package com.four.demo

import android.content.Context
import android.graphics.SurfaceTexture
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.Surface
import android.view.TextureView
import android.view.View
import android.widget.Toast
import com.net.api.RpcApi
import com.net.api.base.BaseObserver
import com.net.api.base.OnHeaderRespListener
import com.net.api.user.UserApi
import com.net.api.userdevice.UserDeviceApi
import com.xciot.lib.XcDevApi
import com.xciot.lib.XcDevApi.*
import com.xciot.lib.XcDevManager
import com.xciot.lib.XcPlayer
import com.xciot.lib.`val`.C_FLIP_TYPE
import com.xciot.lib.media.VideoDecoder
import com.xciot.lib.rx.RxObserver
import kotlinx.android.synthetic.main.activity_main.*
import user.Login.Resp

/**
 * 需要在App初始化sdk，登录后将UID 和pwd调用xcSdkSetUserInfo设置到sdk
 * 所有的命令都是建立在连接建立的情况下，连接断开命令不会成功。
 */
class MainActivity : AppCompatActivity() {

    val TAG = "SDK_DEMO"
    private var mContext : Context? = null
    val mAccount = "17313101213"
    val mPassword = "Aa123456"
    val mCountry = "86"
    val mLoginLang = "zh"
    private var mToken : String? = null
    private var mUid : String? = null
    private var mDid : String? = "PPAVT100004DD62FDB"//"PPAVT100004ED47044"
    private var mXcPlayer : XcPlayer = XcPlayer()
    private var mSurface : Surface?= null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // C app
        RpcApi.CLIENT_ID = RpcApi.CLIENT_ID_C
        RpcApi.CLIENT_SECKEY = RpcApi.CLIENT_SECKEY_C

        mContext = this
        mXcPlayer.prepareAudioPlayer()
        texture_view.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
            override fun onSurfaceTextureAvailable(surfaceTexture: SurfaceTexture, i: Int, i1: Int) {
                mSurface = Surface(surfaceTexture)
            }

            override fun onSurfaceTextureSizeChanged(surfaceTexture: SurfaceTexture, i: Int, i1: Int) {
                mSurface = Surface(surfaceTexture)
            }

            override fun onSurfaceTextureDestroyed(surfaceTexture: SurfaceTexture): Boolean {
                mSurface = null
                return false
            }

            override fun onSurfaceTextureUpdated(surfaceTexture: SurfaceTexture) {

            }
        }
        btn_login.setOnClickListener({rpcLogin()})
        btn_send_device_seccode.setOnClickListener({rpcSendCode()})
        btn_add_device.setOnClickListener({rpcAddDev()})
        btn_del_device.setOnClickListener({rpcDelDev()})
        btn_start_conn.setOnClickListener({sdkConnDev()})
        btn_stop_conn.setOnClickListener({sdkStopDev()})
        btn_conn_mode.setOnClickListener({sdkConnModel()})
        btn_video_play.setOnClickListener({sdkVideoPlay()})
        btn_video_pause.setOnClickListener({sdkVideoPause()})
        btn_audio_play.setOnClickListener({sdkAudioPlay()})
        btn_audio_pause.setOnClickListener({sdkAudioPause()})
        btn_down_speed.setOnClickListener({sdkDownSpeed()})
        btn_up_speed.setOnClickListener({sdkUpSpeed()})
        btn_whole_speed.setOnClickListener({ updateResult("xcSdkGetConnWholeSpeed ${xcSdkGetConnWholeSpeed(mDid)}")})
        btn_set_timeo.setOnClickListener({ updateResult("xcSdkSetWaitTimeo 3000 ret = ${xcSdkSetWaitTimeo(3000)}")})
        btn_get_timeo.setOnClickListener({ updateResult("xcSdkGetWaitTimeo ${xcSdkGetWaitTimeo()}")})
        btn_config_get.setOnClickListener({ xcConfigGet(mDid, 1, object : IConfig {
            override fun onConfig(ssid: String?, qos: Int, flip: Int, led_mode: Int, ircut_mode: Int, secret: Int) {
                updateResult("onConfig $mDid, ssid=$ssid, qos=$qos, flip=$flip, led_mode=$led_mode, ircut=$ircut_mode, secret=$secret")
            }
        })})
        btn_video_qos_set.setOnClickListener({ updateResult("xcVideoQosSet ret=${xcVideoQosSet(mDid, 1, 40, 50)}") })
        btn_flip_set.setOnClickListener({ updateResult("xcFlipSet ret=${xcFlipSet(mDid, 1, C_FLIP_TYPE.TURN_180)}") })
        btn_flip_get.setOnClickListener({ updateResult("xcFlipGet ret=${xcFlipGet(mDid, 1)}") })
        btn_ircut_set.setOnClickListener({ updateResult("xcIrcutSet ret=${xcIrcutSet(mDid, 1, 3)}")})
        btn_ircut_get.setOnClickListener({updateResult("xcIrcutGet = ${xcIrcutGet(mDid, 1)}")})
        btn_led_set.setOnClickListener({updateResult("xcALedSet ret = ${xcALedSet(mDid, 1, 2)}")})
        btn_led_get.setOnClickListener({updateResult("xcALedSet ret = ${xcALedGet(mDid, 1)}")})

        btn_secret_set.setOnClickListener({updateResult("xcASecretSet ret = ${xcASecretSet(mDid, 1, 1)}")})
        btn_secret_get.setOnClickListener({updateResult("xcASecretGet ret = ${xcASecretGet(mDid, 1)}")})
        btn_sd_info.setOnClickListener({updateResult("xcAStorageinfo ret = ${xcAStorageinfo(mDid, 1)}")})
        btn_sd_format.setOnClickListener({updateResult("xcAStorageFormat ret = ${xcAStorageFormat(mDid, 1)}")})

        btn_reset.setOnClickListener({updateResult("xcAReset ret = ${xcAReset(mDid, 1)}")})
        btn_reboot.setOnClickListener({updateResult("xcAReboot ret = ${xcAReboot(mDid, 1)}")})
        btn_vol_set.setOnClickListener({updateResult("xcAVolumeSet ret = ${xcAVolumeSet(mDid, 1, 5)}")})
        btn_vol_get.setOnClickListener({updateResult("xcAVolumeGet ret = ${xcAVolumeGet(mDid, 1)}")})
        btn_powerfreq_set.setOnClickListener({updateResult("xcAPowerfreqSet ret = ${xcAPowerfreqSet(mDid, 1, 50)}")})
        btn_powerfreq_get.setOnClickListener({updateResult("xcAPowerfreqGet ret = ${xcAPowerfreqGet(mDid, 1)}")})
        btn_rom_upgrade.setOnClickListener({updateResult("xcAFirmwareNotify ret = ${xcAFirmwareNotify(mDid, 1, object : IRomUpgradeCallback {
            override fun onRomUpgrade(conn_id: Int, channel: Int, rate: Int) {
                runOnUiThread({
                    updateResult("$mDid, $conn_id, rate=$rate")
                })

            }
        })}")})
        btn_notify_set.setOnClickListener({updateResult("xcANotifySet ret = ${xcANotifySet(mDid, 1, 1,
                intArrayOf(1, 2), 2, intArrayOf(1, 2, 4), 3, intArrayOf(1, 2), intArrayOf(1, 2), 2, 5)}")})
        btn_notify_get.setOnClickListener({updateResult("xcANotifyGet ret = ${xcANotifyGet(mDid, 1)}")})
        btn_powerfreq_test.setOnClickListener({ xcCustomCmd() })
    }

    override fun onDestroy() {
        super.onDestroy()
        mXcPlayer.releaseAudioPlayer()
        mXcPlayer.releaseVideoCodec()
    }

    private fun xcCustomCmd() {
        var req = ipc.CustomCmd.Req.newBuilder().addAllArgInt32(listOf<Int>(1,2)).addArgInt32(2).build()
        var resp = XcDevApi.xcCustomCmd(mDid, req)
        updateResult("xcCustomCmd resp = $resp")
    }

    private fun sdkUpSpeed() {
        XcDevManager.xcSdkGetConnUpSpeed(mDid, object : RxObserver<Int>() {
            override fun _onNext(t: Int?) {
                updateResult("$mDid Up Speed $t")
            }

            override fun _onError() {
                updateResult("$mDid Up Speed error")
            }
        })
    }

    private fun sdkDownSpeed() {
        XcDevManager.xcSdkGetConnDownSpeed(mDid, object : RxObserver<Int> () {
            override fun _onNext(t: Int?) {
                updateResult("$mDid downSpeed $t")
            }

            override fun _onError() {
                updateResult("$mDid  downSpeed _onError")
            }
        })
    }

    private fun sdkConnModel() {
        var mode = XcDevApi.xcSdkGetConnMode(mDid)
        updateResult("conn mode: $mode")
    }

    fun updateResult(msg: String) {
        tv_result.text = msg
    }

    private fun rpcLogin() {
        //String account, String pwd, String countryCode, RpcApi.LOGIN_TYPE loginType, RpcApi.ACCOUNT_TYPE accountType, String loginDevId, String loginDevInfo, String loginLang, RpcApi.LOGIN_OS loginOs, OnHeaderRespListener onHeaderRespListener, BaseObserver<user.Login.Resp> observer
        UserApi.getInstance().login(mAccount, mPassword, mCountry,
                RpcApi.LOGIN_TYPE.APP, RpcApi.ACCOUNT_TYPE.MOBILE, "loginDevId",
                "loginDevInfo", mLoginLang, RpcApi.LOGIN_OS.ANDPHONE,
                mOnHeaderRespListener,
                object : BaseObserver<Resp>() {
                    override fun onNext(t: Resp) {
                        super.onNext(t)
                        mToken = t.accessToken
                        mUid = t.userId
                        ALog.i("rpcLogin mToken=$mToken")
                        ALog.i("rpcLogin mUid=$mUid")
                        XcDevManager.xcSdkSetUserInfo(mUid.toString(), mPassword,
                                object : RxObserver<Int>() {
                                    override fun _onNext(t: Int?) {
                                    }

                                    override fun _onError() {
                                    }

                                })
                    }

                    override fun onError(e: Throwable) {
                        super.onError(e)
                        ALog.e("rpcLogin e=${e.toString()}")
                        updateResult("login error $e")
                    }
                })
    }

    private fun rpcSendCode() {
        UserApi.getInstance().sendVcode(mAccount, mCountry,
                RpcApi.ACCOUNT_TYPE.MOBILE, RpcApi.VCODE_TYPE.BIND,
                mOnHeaderRespListener,
                object : BaseObserver<user.SendVcode.Resp>() {
                    override fun onNext(t: user.SendVcode.Resp) {
                        super.onNext(t)
                        ALog.i("rpcLogin t=$t")
                    }

                    override fun onError(e: Throwable) {
                        super.onError(e)
                        ALog.e("rpcLogin e=${e.toString()}")
                    }
                })
    }

    private fun rpcAddDev() {
        //String token, String did, String name, String sec_vcode, final OnHeaderRespListener onHeaderRespListener, BaseObserver<userdevice.AddDevice.Resp> observer
        UserDeviceApi.getInstance().addDevice(mToken, mDid,
                "dev-name", "",
                mOnHeaderRespListener,
                object : BaseObserver<userdevice.AddDevice.Resp>() {

                })
    }

    private fun rpcDelDev() {
        //String token, String did, final OnHeaderRespListener onHeaderRespListener, BaseObserver<userdevice.DeleteDevice.Resp> observer
        UserDeviceApi.getInstance().deleteDevice(mToken, mDid,
                mOnHeaderRespListener,
                object : BaseObserver<userdevice.DeleteDevice.Resp>() {

                })
    }

    private fun sdkConnDev() {
        XcDevManager.xcSdkConnectDev(mDid, mOnConnListener)
    }

    private fun sdkStopDev() {
        XcDevManager.xcSdkStopConn(mDid,
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid stopDev $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid stopDev _onError")
                    }
                })
    }

    private fun sdkVideoPlay() {
        XcDevManager.xcSetVideoCallback(
                { connId, frame, type, keyFrame, timeStamp ->
                    //updateResult("$mDid videoCallback connId= $connId, frame=$frame, type=$type, keyFrame=keyFrame")
                    ALog.i("$mDid videoCallback connId= $connId, frame=$frame, type=$type, keyFrame=$keyFrame")
                    mXcPlayer.playVideoFrameCodec(mSurface, frame, type, keyFrame, object : VideoDecoder.OnOutImageListener{
                        override fun onoutimage() {
                            updateResult("playVideoFrameCodec onoutimage OK")
                        }
                    })
                },
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid sdkVideoPlay ret= $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid sdkVideoPlay _onError")
                    }

                }
        )
        XcDevManager.xcVideoPlay(mDid, 1, 40, 22,
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid xcVideoPlay ret= $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid xcVideoPlay _onError")
                    }
                })
    }

    private fun sdkVideoPause() {
        XcDevManager.xcVideoPause(mDid, 1,
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid xcVideoPause $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid xcVideoPause _onError")
                    }

                })
    }

    private fun sdkAudioPlay() {
        mXcPlayer.startAudioPlayer()
        XcDevManager.xcSetAudioCallback(
                { connId, frame, type ->
                    ALog.i("$mDid audioCallback connId= $connId, frame=$frame, type=$type")
                    mXcPlayer.playAudioFrame(frame)
                },
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid xcSetAudioCallback $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid xcSetAudioCallback error")
                    }
                })
        XcDevManager.xcAudioPlay(mDid,
                { code, codec, rate, bit, track ->
                    ALog.i("xcAudioPlay $code , $codec, $rate, $bit, $track")
                },
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid xcAudioPlay $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid xcAudioPlay error")
                    }

                })
    }

    private fun sdkAudioPause() {
        mXcPlayer.pauseAudioPlayer()
        XcDevManager.xcAudioPause(mDid,
                object : RxObserver<Int>() {
                    override fun _onNext(t: Int?) {
                        updateResult("$mDid xcAudioPause $t")
                    }

                    override fun _onError() {
                        updateResult("$mDid xcAudioPause error")
                    }

                })
    }

    var mOnClickableSpan = View.OnClickListener { v ->
        when (v.id) {
            R.id.btn_login -> rpcLogin()
            R.id.btn_send_device_seccode -> rpcSendCode()
            R.id.btn_add_device -> rpcAddDev()
            R.id.btn_del_device -> rpcDelDev()
            R.id.btn_start_conn -> sdkConnDev()
            R.id.btn_stop_conn -> sdkStopDev()
            R.id.btn_video_play -> sdkVideoPlay()
            R.id.btn_video_pause -> sdkVideoPause()
            R.id.btn_audio_play -> sdkAudioPlay()
            R.id.btn_audio_pause -> sdkAudioPause()
        }
    }

    var mOnHeaderRespListener = OnHeaderRespListener { errorCode ->
        ALog.i("errorCode $errorCode")
        if (errorCode != 0) {
            Toast.makeText(mContext, "ErrorCode = $errorCode", Toast.LENGTH_SHORT).show()
        } else {
            updateResult("Api ok")
            Toast.makeText(mContext, "Ok", Toast.LENGTH_SHORT).show()
        }
    }

    var mOnConnListener = object : OnConnListener {
        override fun onConnect(deviceId: String?, connId: Int) {
            ALog.i("onConnect $deviceId connId=$connId")
            runOnUiThread {
                tv_conn_state.text = "$deviceId conn state: $connId OK"
                updateResult("$deviceId onConnected, $connId")
            }
        }

        override fun onTimeout(deviceId: String?, connId: Int) {
            ALog.i("onTimeout $deviceId connId=$connId")
            runOnUiThread {
                tv_conn_state.text = "$deviceId conn state: $connId onTimeout"
                updateResult("$deviceId onTimeout, $connId")
            }
        }

        override fun onDisconnect(deviceId: String?, connId: Int) {
            ALog.i("onDisconnect $deviceId connId=$connId")
            runOnUiThread {
                tv_conn_state.text = "$deviceId conn state: $connId onDisconnect"
                updateResult("$deviceId onDisconnect, $connId")
            }
        }

    }
}
